package com.siyoumi.component;

import com.alibaba.fastjson.JSON;
import com.siyoumi.entity.SysLogService;
import com.siyoumi.util.XDate;
import com.siyoumi.util.XStr;
import com.siyoumi.validator.XValidator;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;

import java.time.Duration;
import java.time.LocalDateTime;
import java.util.*;

//log流水线
@Slf4j
@Data
public class LogPipeLine {
    //线程对象
    static final private ThreadLocal<LogPipeLine> tl0 = new ThreadLocal<>();
    static final private ThreadLocal<LogPipeLine> tl1 = new ThreadLocal<>();

    static public ThreadLocal<LogPipeLine> getTl(Integer tag) {
        ThreadLocal<LogPipeLine> tl = tl0;
        if (tag == 1) {
            tl = tl1;
        }
        return tl;
    }

    static public LogPipeLine of() {
        return of(0);
    }

    static public LogPipeLine ofSys() {
        return of(1);
    }

    static public LogPipeLine of(Integer tag) {
        ThreadLocal<LogPipeLine> tl = getTl(tag);
        //同一个线程，只会new 1次
        LogPipeLine util = tl.get();
        if (util != null) {
            return util;
        }

        util = new LogPipeLine();
        tl.set(util);
        util.setTag(tag);
        return util;
    }

    static public void tlRemove() {
        tlRemove(0);
    }

    static public void tlRemove(Integer tag) {
        ThreadLocal<LogPipeLine> tl = getTl(tag);
        tl.remove();
    }


    private List<String> logMsgList = new ArrayList<>();
    private LocalDateTime lastTime;
    private Map<String, Object> mapAppend = new HashMap<>(); //追加参数
    private Integer tag = 0;


    public void clear() {
        setLogMsgList(new ArrayList<>());
    }

    public void saveDb(String method, String x) {
        saveDb(method, x, false);
    }

    /**
     * 记录日志
     *
     * @param method
     * @param x
     */
    public void saveDb(String method, String x, Boolean logDb) {
        String msg = getLogMsg();
        //释放对象
        tlRemove(getTag());
        //
        if (XStr.isNullOrEmpty(msg)) {
            log.debug("日志内容为空，不插入数据");
            return;
        }

        if (getMapAppend() == null) {
            setMapAppend(new HashMap<>());
        }
        String logStr00 = (String) getMapAppend().get("log_str_00");
        String logStr01 = (String) getMapAppend().get("log_str_01");

        if (logDb) {
            SysLogService.getBean().addSysLog(method, logStr00, msg, logStr01);
        } else {
            StringBuilder sb = new StringBuilder();
            sb.append(XStr.format("method: {0}[{1}]\n", method, x));
            if (XStr.hasAnyText(logStr00)) {
                sb.append(XStr.format("log_str_00: {0}\n", logStr00));
            }
            if (XStr.hasAnyText(logStr01)) {
                sb.append(XStr.format("log_str_01: {0}\n", logStr01));
            }
            sb.append(XStr.format("----msg----\n{0}", msg));
            log.info(sb.toString());
        }
    }

    /**
     * 获取步骤文字
     *
     * @return string
     */
    public String getLogMsg() {
        StringBuilder str = new StringBuilder();
        int index = 1;//序号
        for (String msg : getLogMsgList()) {
            str.append(index).append("：").append(msg).append(System.getProperty("line.separator"));
            index++;
        }

        return str.toString();
    }

    /**
     * 方法名称
     *
     * @param funName
     */
    public void setFunName(String funName) {
        setAppendData("log_str_00", funName);
    }

    /**
     * 追加参数
     *
     * @param key
     * @param val
     */
    public void setAppendData(String key, String val) {
        String[] keys = {
                //"log_wxuser_id",
                //"log_id_src",
                "log_str_00",
                "log_str_01",
                //"log_str_02",
                //"log_str_03",
        };
        List<String> keyArr = Arrays.asList(keys);
        if (!keyArr.contains(key)) {
            XValidator.err(20098, "key error");
        }

        mapAppend.put(key, val);
    }

    public void setLogMsg(String... msg) {
        setLogMsg(XStr.concat(msg));
    }

    public void setLogMsgFormat(String msg, String... args) {
        setLogMsg(XStr.format(msg, args));
    }

    /**
     * 步骤文字记录
     *
     * @param msg
     */
    public void setLogMsg(Object msg) {
        String logMsg = "";
        if (msg instanceof String) {
            logMsg = (String) msg;
        } else {
            logMsg = JSON.toJSONString(msg);
        }

        LocalDateTime now = LocalDateTime.now();//时间
        int timeMs = 0;//离上步骤-相差多少毫秒
        if (getLastTime() != null) {
            Duration duration = Duration.between(getLastTime(), now);
            timeMs = Integer.parseInt(String.valueOf(duration.toMillis()));
        }

        //[2023-07-04 09:58:55] [0ms] testabc
        logMsg = "[" + XDate.format(now,"HH:mm:ss") + "] [" + timeMs + "ms] " + logMsg;
        getLogMsgList().add(logMsg);
        setLastTime(now);
        //log.info(logMsg);
    }


}
